/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

//#ifndef TRIANGLEGEOMETRY
//#define TRIANGLEGEOMETRY

#include <向量.h>
#include <矩阵.h>
#include <Vector/向量运算.h>
#include <SIMD/CPU_向量计算.h>


typedef struct {
	vec3 pointA;
	vec3 pointB;
	vec3 pointC;
}S_三角形_;




//三角形中心点坐标
inline void f_三角形中心坐标(float 中心点坐标[3], const float PointA[3], const float PointB[3], const float PointC[3]) {
	中心点坐标[0] = (PointA[0] + PointB[0] + PointC[0]) / 3;
	中心点坐标[1] = (PointA[1] + PointB[1] + PointC[1]) / 3;
	中心点坐标[2] = (PointA[2] + PointB[2] + PointC[2]) / 3;
}

inline vec3 f_三角形中心坐标(const vec3& PointA, const vec3& PointB, const vec3& PointC) {
	return { (PointA.x + PointB.x + PointC.x) / 3.0f,
				(PointA.y + PointB.y + PointC.y) / 3.0f,
				(PointA.z + PointB.z + PointC.z) / 3.0f
	};
}

Inline S_VecSphere f_graph_取三角形球形包围(const vec3& PointA, const vec3& PointB, const vec3& PointC) {
	S_VecSphere s;
	s.pos = { (PointA.x + PointB.x + PointC.x) / 3.0f,
				(PointA.y + PointB.y + PointC.y) / 3.0f,
				(PointA.z + PointB.z + PointC.z) / 3.0f
	};

	s.radius = vec_len(s.pos - PointA);
	s.radius = DEF_Max(s.radius, vec_len(s.pos - PointB));
	s.radius = DEF_Max(s.radius, vec_len(s.pos - PointC));

	return s;
}




//两线段距离


//三角形外切圆半径
inline float f_三角形外切圆半径(const float PointA[3], const float PointB[3], const float PointC[3]) {
	float vec0[3] = { PointB[0] - PointA[0], PointB[1] - PointA[1], PointB[2] - PointA[2] };
	float vec1[3] = { PointC[0] - PointA[0], PointC[1] - PointA[1], PointC[2] - PointA[2] };
	float ABLen = vec_归一化(vec0);
	vec_归一化(vec1);
	float dot = vec_dot(vec0, vec1);
	//得出垂直边长度
	float AC = ABLen * dot;

	return (AC / dot) / 2;
}

//点到平面的距离
inline float f_点到平面距离(const float PointA[3], const float PointB[3], const float PointC[3], const float OutSidePoint[3]) {
	float vecAB[3] = { PointB[0] - PointA[0], PointB[1] - PointA[1], PointB[2] - PointA[2] };
	float vecAC[3] = { PointC[0] - PointA[0], PointC[1] - PointA[1], PointC[2] - PointA[2] };
	float vecPointToPlane[3] = { OutSidePoint[0] - PointA[0], OutSidePoint[1] - PointA[1], OutSidePoint[2] - PointA[2] };

	vec_归一化(vecAB);
	vec_归一化(vecAC);
	vec_归一化(vecPointToPlane);
	//计算平面法线
	float pn[3] = { 0.0,1.0,0.0 };
	vec_叉积(vecAB, vecAC, pn);

	//得到点和平面的距离
	return vec_dot(pn, vecPointToPlane) / 向量_两向量距离(pn);
}


inline float f_点到平面法线(const float PointA[3], const float PointB[3], const float PointC[3],
	const float OutSidePoint[3], float PNormal[3]) {

	float vecAB[3] = { PointB[0] - PointA[0], PointB[1] - PointA[1], PointB[2] - PointA[2] };
	float vecAC[3] = { PointC[0] - PointA[0], PointC[1] - PointA[1], PointC[2] - PointA[2] };
	float vecPointToPlane[3] = { OutSidePoint[0] - PointA[0], OutSidePoint[1] - PointA[1], OutSidePoint[2] - PointA[2] };

	vec_归一化(vecAB);
	vec_归一化(vecAC);
	//vec_normalize(vecPointToPlane);
	//计算平面法线
	vec_叉积(vecAB, vecAC, PNormal);
	float dis = vec_归一化(PNormal);

	//得到点和平面的距离
	return vec_dot(vecPointToPlane, PNormal) / dis;
}


//绕点旋转
inline void f_绕点旋转(const float point[3], const float dir, const float angle[3], float pos[3]) {
	float mat[16] = { 0.0 };
	Matrix4X4f_Identity(mat);
	float tranform[3] = { 0, 0.0, dir };

	Matrix4X4_Location(mat, tranform);
	Matrix4X4_Rotation(mat, angle);

	Matrix4X4_TranformVec(pos, point, mat);
}


inline float VecHamilton(const float vec[3], const float point[3], const float oper) {
	return (oper*vec[0]) / (oper*point[0]) + (oper*vec[1]) / (oper*point[1]) + (oper*vec[2]) / (oper*point[2]);
}



//取三角形AB边
inline float geometry_getTriangleEdgeAB(const S_三角形_& triangle, float vecAB[3]){
	vecAB[0] = triangle.pointB.x - triangle.pointA.x;
	vecAB[1] = triangle.pointB.y - triangle.pointA.y;
	vecAB[2] = triangle.pointB.z - triangle.pointA.z;

	return vec_归一化(vecAB);
}

//取三角形BC边
inline float geometry_getTriangleEdgeBC(const S_三角形_& triangle, float vecBC[3]){
	vecBC[0] = triangle.pointC.x - triangle.pointB.x;
	vecBC[1] = triangle.pointC.y - triangle.pointB.y;
	vecBC[2] = triangle.pointC.z - triangle.pointB.z;

	return vec_归一化(vecBC);
}

//取三角形AC边
inline float geometry_getTriangleEdgeAC(const S_三角形_& triangle, float vecAC[3]){
	vecAC[0] = triangle.pointC.x - triangle.pointA.x;
	vecAC[1] = triangle.pointC.y - triangle.pointA.y;
	vecAC[2] = triangle.pointC.z - triangle.pointA.z;

	return vec_归一化(vecAC);
}


//取三角形内点
inline void geometry_GetTriangleInsidePoint(const float vecAB[3], const float vecBC[3], const float spacing[2], float point[3]){
	point[0] = vecAB[0]*spacing[0] + vecBC[0]*spacing[1];
	point[1] = vecAB[1]*spacing[0] + vecBC[1]*spacing[1];
	point[2] = vecAB[2]*spacing[0] + vecBC[2]*spacing[1];
}

inline void geometry_GetTriangleInsidePoint(const S_三角形_ triangle, const float spacing[2], float point[3]){
	float vecAB[3] = {triangle.pointB.x-triangle.pointA.x
			  ,triangle.pointB.y-triangle.pointA.y
			  ,triangle.pointB.z-triangle.pointA.z};
	float vecAC[3] = {triangle.pointC.x-triangle.pointA.x
			  ,triangle.pointC.y-triangle.pointA.y
			  ,triangle.pointC.z-triangle.pointA.z};


}


//计算法线
inline void geometry_TriangleNormal(const S_三角形_ triangle, float normal[3]){
	float vecAB[3] = {0.0,0.0,0.0};
	float vecAC[3] = {0.0,0.0,0.0};
	geometry_getTriangleEdgeAB(triangle, vecAB);
	geometry_getTriangleEdgeAC(triangle, vecAC);

	vec_归一化(vecAB);
	vec_归一化(vecAC);
	vec_叉积(vecAB, vecAC, normal);
	vec_归一化(normal);
}
inline void geometry_TriangleNormal(const float pointA[3], const float pointB[3], const float pointC[3], float normal[3]){
	float vecAB[3] = {0.0,0.0,0.0};
	float vecAC[3] = {0.0,0.0,0.0};

	vecAB[0] = pointB[0]-pointA[0];
	vecAB[1] = pointB[1]-pointA[1];
	vecAB[2] = pointB[2]-pointA[2];

	vecAC[0] = pointC[0]-pointA[0];
	vecAC[1] = pointC[1]-pointA[1];
	vecAC[2] = pointC[2]-pointA[2];

	//Vec_normalize(vecAB);
	//Vec_normalize(vecAC);
	vec_叉积(vecAB, vecAC, normal);
	vec_归一化(normal);
}

inline float f_点到平面距离(const S_三角形_& triangle, const float OutSidePoint[3], float PNormal[3]){
	float vecAB[3] = {0.0,0.0,0.0};
	float vecAC[3] = {0.0,0.0,0.0};
	geometry_getTriangleEdgeAB(triangle, vecAB);
	geometry_getTriangleEdgeAC(triangle, vecAC);
	//float vecAB[3] = {PointB[0] - PointA[0], PointB[1] - PointA[1], PointB[2] - PointA[2]};
	//float vecAC[3] = {PointC[0] - PointA[0], PointC[1] - PointA[1], PointC[2] - PointA[2]};
	float vecPointToPlane[3] =
	{OutSidePoint[0] - triangle.pointA.x, OutSidePoint[1] - triangle.pointA.y, OutSidePoint[2] - triangle.pointA.z};

	vec_归一化(vecAB);
	vec_归一化(vecAC);
	//计算平面法线
	vec_叉积(vecAB, vecAC, PNormal);
	float dis = vec_归一化(PNormal);


	//得到点和平面的距离
	return vec_dot(vecPointToPlane, PNormal) / dis;
}

//沿法线移动
inline void triangl_normalMove(S_三角形_ triangle, const float dis){
	float vecAB[3] = {0.0,0.0,0.0};
	float vecAC[3] = {0.0,0.0,0.0};
	geometry_getTriangleEdgeAB(triangle, vecAB);
	geometry_getTriangleEdgeAC(triangle, vecAC);

	vec_归一化(vecAB);
	vec_归一化(vecAC);

	//计算平面法线
	float PNormal[3];
	vec_叉积(vecAB, vecAC, PNormal);
	vec_归一化(PNormal);
	vec_自乘(PNormal, dis);

	vec_自加((float32*)&triangle.pointA, PNormal);
	vec_自加((float32*)&triangle.pointB, PNormal);
	vec_自加((float32*)&triangle.pointC, PNormal);


}


S_VecSphere f_graph_取三角形球形包围(vec3* 三角形);












//#endif // TRIANGLEGEOMETRY

/*inline float f_两线段距离(const float* vec0, const float* vec1) {
	float normal[3] = { 0.0, 0.0, 0.0 };
	vec_叉积(normal, vec0, vec1);
	float dot = vec_dot(vec0, vec1);
	return dot / 向量_两向量距离(normal);
}*/